package com.baomidou.springwind.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.kisso.annotation.Permission;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.springwind.entity.CityOrder;
import com.baomidou.springwind.entity.NetworkNode;
import com.baomidou.springwind.entity.Project;
import com.baomidou.springwind.enums.FileTypeEnum;
import com.baomidou.springwind.enums.NodeTypeEnum;
import com.baomidou.springwind.pojo.CityDrivingRoute;
import com.baomidou.springwind.pojo.CityPeopleGroup;
import com.baomidou.springwind.pojo.DrivingRoute;
import com.baomidou.springwind.pojo.Test;
import com.baomidou.springwind.service.*;
import com.baomidou.springwind.utils.ParamMap;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.io.*;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.DecimalFormat;
import java.util.*;

/**
 * <p>
 * 仓储模拟相关操作
 * </p>
 *
 * @Author demo
 * @Date 2017-5-28
 */
@Controller
@RequestMapping("/network")
public class NetworkNodeController extends BaseController {

    @Autowired
    private NetworkNodeService networkNodeService;
    @Autowired
    private CityOrderService cityOrderService;
    @Autowired
    private ProjectService projectService;

    private DecimalFormat df = new DecimalFormat("##.##");

    private static final double EARTH_RADIUS = 6378137;

    @Permission("1001")
    @RequestMapping("/view/{batchId}")
    public String list(@PathVariable Long batchId, Model model) {
        model.addAttribute("batchId", batchId);
        return pjaxPath("/lpp/network/main", model);
    }

    @Permission("1001")
    @RequestMapping("/inputParameters")
    public String uploadFile(Integer fileType, Model model) {
        model.addAttribute("prjList", projectService.getUserAllProjects());
        return "/lpp/network/city/input_item";
    }

    @ResponseBody
    @Permission("1001")
    @RequestMapping("/map")
    public String getMap(Long batchId, Model model) {
        List<NetworkNode> nodeList = networkNodeService.getNetworkNodeList(batchId);
        List<NetworkNode> dcList = new ArrayList<NetworkNode>();
        List<NetworkNode> cusList = new ArrayList<NetworkNode>();
        for (NetworkNode node : nodeList) {
            if (node.getNodeType() == NodeTypeEnum.DISTRIBUTE_CENTER.type) {
                dcList.add(node);
            } else if (node.getNodeType() == NodeTypeEnum.CUSTOM.type) {
                cusList.add(node);
            }
        }
        Map<NetworkNode, List<NetworkNode>> relationMap = new HashMap<NetworkNode, List<NetworkNode>>();
        for (NetworkNode dcNode : dcList) {
            relationMap.put(dcNode, new ArrayList<NetworkNode>(5));
        }
        for (NetworkNode cusNode : cusList) {
            NetworkNode nearestNode = findDcNode(cusNode, dcList);
            List<NetworkNode> toNodeList = relationMap.get(nearestNode);
            double distance = getDistance(nearestNode, cusNode);
            toNodeList.add(cusNode);
        }
        JSONArray data = new JSONArray();
        Random random = new Random(47);
        for (Map.Entry<NetworkNode, List<NetworkNode>> entry : relationMap.entrySet()) {
            JSONObject serie = new JSONObject();
            JSONArray res = new JSONArray();
            JSONArray nodes = new JSONArray();
            NetworkNode fromNode = entry.getKey();
            for (NetworkNode toNode : entry.getValue()) {
                res.add(parseRes(fromNode, toNode));
                nodes.add(new NodeData("", Arrays.asList(toNode.getCoordinateY(), toNode.getCoordinateX(), random.nextInt(100))));
            }
//            nodes.add(new NodeData("", Arrays.asList(fromNode.getCoordinateX(), fromNode.getCoordinateY(), 50)));
            serie.put("name", fromNode.getNodeName());
            serie.put("res", res);
            serie.put("nodes", nodes);
            data.add(serie);
        }

        return callbackSuccess(data);
    }

    @ResponseBody
    @Permission("1001")
    @RequestMapping("/bar1")
    public String getBar1(Long batchId, Model model) {
        List<NetworkNode> nodeList = networkNodeService.getNetworkNodeList(batchId);
        List<NetworkNode> dcList = new ArrayList<NetworkNode>();
        List<NetworkNode> cusList = new ArrayList<NetworkNode>();
        for (NetworkNode node : nodeList) {
            if (node.getNodeType() == NodeTypeEnum.DISTRIBUTE_CENTER.type) {
                dcList.add(node);
            } else if (node.getNodeType() == NodeTypeEnum.CUSTOM.type) {
                cusList.add(node);
            }
        }
        Map<NetworkNode, List<NetworkNode>> relationMap = new HashMap<NetworkNode, List<NetworkNode>>();
        for (NetworkNode dcNode : dcList) {
            relationMap.put(dcNode, new ArrayList<NetworkNode>(5));
        }
        NetworkNode original = dcList.get(0);
        double currentCost = (dcList.size() - 1) * 5000000;
        double originalCost = 0;
        for (NetworkNode cusNode : cusList) {
            NetworkNode nearestNode = findDcNode(cusNode, dcList);
            currentCost += getDistance(nearestNode, cusNode);
            originalCost += getDistance(original, cusNode);
        }
        JSONObject ret = new JSONObject();
        ret.put("name", Arrays.asList("优化前", "优化后"));
        ret.put("value", Arrays.asList(df.format(originalCost / 10000), df.format(currentCost / 10000)));
        return callbackSuccess(ret);
    }

    @ResponseBody
    @Permission("1001")
    @RequestMapping("/gauge")
    public String getGauge(Long batchId, Model model) {
        List<NetworkNode> nodeList = networkNodeService.getNetworkNodeList(batchId);
        List<NetworkNode> dcList = new ArrayList<NetworkNode>();
        List<NetworkNode> cusList = new ArrayList<NetworkNode>();
        for (NetworkNode node : nodeList) {
            if (node.getNodeType() == NodeTypeEnum.DISTRIBUTE_CENTER.type) {
                dcList.add(node);
            } else if (node.getNodeType() == NodeTypeEnum.CUSTOM.type) {
                cusList.add(node);
            }
        }
        Map<NetworkNode, List<NetworkNode>> relationMap = new HashMap<NetworkNode, List<NetworkNode>>();
        for (NetworkNode dcNode : dcList) {
            relationMap.put(dcNode, new ArrayList<NetworkNode>(5));
        }
        NetworkNode original = dcList.get(0);
        double currentCost = 0;
        double originalCost = 0;
        for (NetworkNode cusNode : cusList) {
            NetworkNode nearestNode = findDcNode(cusNode, dcList);
            currentCost += getDistance(nearestNode, cusNode);
            originalCost += getDistance(original, cusNode);
        }
        return callbackSuccess(df.format((originalCost - currentCost) * 100 / originalCost));
    }

    @ResponseBody
    @Permission("1001")
    @RequestMapping("/bar2")
    public String getBar2(Long batchId, Model model) {
        List<NetworkNode> nodeList = networkNodeService.getNetworkNodeList(batchId);
        List<NetworkNode> dcList = new ArrayList<NetworkNode>();
        List<NetworkNode> cusList = new ArrayList<NetworkNode>();
        for (NetworkNode node : nodeList) {
            if (node.getNodeType() == NodeTypeEnum.DISTRIBUTE_CENTER.type) {
                dcList.add(node);
            } else if (node.getNodeType() == NodeTypeEnum.CUSTOM.type) {
                cusList.add(node);
            }
        }
        Map<NetworkNode, List<NetworkNode>> relationMap = new HashMap<NetworkNode, List<NetworkNode>>();
        for (NetworkNode dcNode : dcList) {
            relationMap.put(dcNode, new ArrayList<NetworkNode>(5));
        }
        Map<NetworkNode, Double> dcCostMap = new HashMap<NetworkNode, Double>();
        for (NetworkNode cusNode : cusList) {
            NetworkNode nearestNode = findDcNode(cusNode, dcList);
            double distance = getDistance(nearestNode, cusNode);
            if (dcCostMap.containsKey(nearestNode)) {
                dcCostMap.put(nearestNode, dcCostMap.get(nearestNode) + distance);
            } else {
                dcCostMap.put(nearestNode, distance);
            }
        }
        JSONObject ret = new JSONObject();
        JSONArray name = new JSONArray();
        JSONArray value = new JSONArray();
        for (Map.Entry<NetworkNode, Double> entry : dcCostMap.entrySet()) {
            name.add(entry.getKey().getNodeName());
            value.add(df.format(entry.getValue() / 10000));
        }
        ret.put("name", name);
        ret.put("value", value);
        return callbackSuccess(ret);
    }




    private JSONObject parseRes(NetworkNode from, NetworkNode to) {
        JSONObject res = new JSONObject();
        res.put("fromName", from.getNodeName());
        res.put("toName", to.getNodeName());
        JSONArray fromCoord = new JSONArray();
        fromCoord.add(from.getCoordinateY());
        fromCoord.add(from.getCoordinateX());
        JSONArray toCoord = new JSONArray();
        toCoord.add(to.getCoordinateY());
        toCoord.add(to.getCoordinateX());
        JSONArray coords = new JSONArray();
        coords.add(fromCoord);
        coords.add(toCoord);
        res.put("coords", coords);
        return res;
    }


    /**
     * 返回最近节点
     */
    private NetworkNode findDcNode(NetworkNode cusNode, List<NetworkNode> dcList) {
        double minDistance = Double.MAX_VALUE;
        NetworkNode dcNode = null;
        for (NetworkNode node : dcList) {
            double distance = getDistance(cusNode, node);
            if (distance < minDistance) {
                dcNode = node;
                minDistance = distance;
            }
        }
        return dcNode;
    }

    //节点间的路径
    private double getDistance(NetworkNode from, NetworkNode to) {
        return getDistance(from.getCoordinateX().doubleValue(), from.getCoordinateY().doubleValue(), to.getCoordinateX().doubleValue(), to.getCoordinateY().doubleValue());
    }

    /**
     * 转化为弧度(rad)
     */
    private static double rad(double d) {
        return d * Math.PI / 180.0;
    }

    /**
     * 基于googleMap中的算法得到两经纬度之间的距离,计算精度与谷歌地图的距离精度差不多，相差范围在0.2米以下
     *
     * @param lon1 第一点的经度
     * @param lat1 第一点的纬度
     * @param lon2 第二点的经度
     * @param lat2 第二点的纬度
     * @return 返回的距离，单位km
     */
    public static double getDistance(double lon1, double lat1, double lon2, double lat2) {
        double radLat1 = rad(lat1);
        double radLat2 = rad(lat2);
        double a = radLat1 - radLat2;
        double b = rad(lon1) - rad(lon2);
        double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
        s = s * EARTH_RADIUS;
        //s = Math.round(s * 10000) / 10000;
        return s;
    }

    /**
     * 登录
     */
    @RequestMapping("/test")
    @Permission("1001")
    public String test(Model model) {
        return "/test";
    }

    /**
     * 登录
     */
    @RequestMapping("/city/group")
    @Permission("1001")
    public String group(Model model) {
        model.addAttribute("prjList", projectService.getUserAllProjects());
        return pjaxPath("/lpp/network/city/group", model);
    }

    /**
     * 登录
     */
    @RequestMapping("/city/transport")
    @Permission("1001")
    public String transport(Model model) {
        return pjaxPath("/lpp/network/city/transport", model);
    }
  /**
     * 登录
     */
    @RequestMapping("/map1")
    @Permission("1001")
    public String map1(Long batchId,Model model) {
        model.addAttribute("batchId",batchId);
        return "/lpp/network/map1";
    }
    /**
     * 登录
     */
    @RequestMapping("/map2")
    @Permission("1001")
    public String map(Long batchId,Model model) {
        model.addAttribute("batchId",batchId);
        return "/lpp/network/map";
    }

    /**
     * 登录
     */
    @RequestMapping("/city/line")
    @Permission("1001")
    public String cityLine(Model model) {
        return  "/lpp/network/city/line";
    }

    @ResponseBody
    @Permission("1001")
    @RequestMapping("/city/heatMap")
    public String heatMap(Model model) throws Exception {
        EntityWrapper<NetworkNode> wrapper = new EntityWrapper<NetworkNode>();
        wrapper.setSqlSelect("node_name nodeName,coordinate_x lat,coordinate_y lng,amount count");
        wrapper.eq("batch_id", getMaxId());
        wrapper.eq("node_type", "3");
        List<Map<String, Object>> mapList = networkNodeService.selectMaps(wrapper);
        return callbackSuccess(mapList);
    }


    @Permission("1001")
    @RequestMapping("/city/view")
    public String city(Model model) throws Exception {
        Long batchId = getMaxId();
        EntityWrapper<NetworkNode> wrapper = new EntityWrapper<NetworkNode>();
//        wrapper.setSqlSelect("node_name nodeName,coordinate_x lat,coordinate_y lng,amount count");
        wrapper.eq("batch_id", batchId);
        wrapper.eq("node_type", "3");
        wrapper.orderBy("node_type");
//        wrapper.eq("node_type", NodeTypeEnum.CUSTOM.getType());
        final List<NetworkNode> nodeList = networkNodeService.selectList(wrapper);
        List<JSONObject> result = new ArrayList<JSONObject>();
        List<DrivingRoute> drivingRoutes = readObj(batchId);
        List<NetworkNode> destinations = new ArrayList<NetworkNode>();
        if (drivingRoutes == null) {
            for (int i = 0; i < nodeList.size(); i++) {
                int j = i + 1;
                while (j < nodeList.size()) {
                    destinations.add(nodeList.get(j));
                    if (destinations.size() == 30) {
                        result.addAll(getBaiduApiResult(nodeList.get(i), destinations));
                        destinations.clear();
                    }
                    j++;
                }
                if (destinations.size() > 0) {
                    result.addAll(getBaiduApiResult(nodeList.get(i), destinations));
                }
                destinations.clear();
            }
            drivingRoutes = new ArrayList<DrivingRoute>();
            int index = 0;
            for (int i = 0; i < nodeList.size(); i++) {
                for (int j = i + 1; j < nodeList.size(); j++) {
                    drivingRoutes.add(
                            new DrivingRoute(nodeList.get(i), nodeList.get(j),
                                    result.get(index).getJSONObject("distance").getLong("value"),
                                    result.get(index).getJSONObject("duration").getLong("value")));
                    index++;
                }
            }
            writeObj(drivingRoutes,batchId);
        }
        LinkedHashMap<NetworkNode, List<NetworkNode>> maps = Test.getMaps(drivingRoutes);
        List<Map<String, Object>> rute = new LinkedList<Map<String, Object>>();
        for (Map.Entry<NetworkNode, List<NetworkNode>> entry : maps.entrySet()) {
            Map<String, Object> map = new HashMap<String, Object>();
            JSONArray array = new JSONArray();
            String path = entry.getKey().getNodeName();
            addNode(entry.getKey(), array);
            List<NetworkNode> children = entry.getValue();
            if (children.size() > 0) {
                path += "-->" + children.get(0).getNodeName();
                addNode(children.get(0), array);
            }
            if (children.size() > 1) {
                path += "-->" + children.get(1).getNodeName();
                addNode(children.get(1), array);
            }
            map.put("path", path);
            map.put("points", JSON.toJSONString(array));
            rute.add(map);
        }
        model.addAttribute("path", rute);
        model.addAttribute("nodeList", nodeList);
        return pjaxPath("/lpp/network/city", model);
    }


    private void addNode(NetworkNode node, JSONArray array) {
        JSONObject json = new JSONObject();
        json.put("lng", node.getCoordinateY());
        json.put("lat", node.getCoordinateX());
        json.put("name", node.getNodeName());
        array.add(json);
    }

    private void writeObj(List<DrivingRoute> drivingRoutes,Long batchId) {
        //序列化对象
        ObjectOutputStream out = null;
        try {
            String path = request.getSession().getServletContext().getRealPath("");
            path = path.substring(0, path.lastIndexOf("\\"));
            path = path.substring(0, path.lastIndexOf("\\"));
            File file = new File(path + "/temp/route/" + batchId + ".obj");
            if (!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }
            out = new ObjectOutputStream(new FileOutputStream(file));
            out.writeInt(drivingRoutes.size());
            for (DrivingRoute drivingRoute : drivingRoutes) {
                out.writeObject(drivingRoute);    //写入customer对象
            }
        } catch (Exception e) {

        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private List<DrivingRoute> readObj(Long batchId) throws Exception {
        //序列化对象
        try {
            String path = request.getSession().getServletContext().getRealPath("");
            path = path.substring(0, path.lastIndexOf("\\"));
            path = path.substring(0, path.lastIndexOf("\\"));
            File file = new File(path + "/temp/route/" + batchId + ".obj");
            if (!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
            int size = ois.readInt();
            List<DrivingRoute> drivingRoutes = new ArrayList<DrivingRoute>(size);
            while (size-- > 0) {
                drivingRoutes.add((DrivingRoute) ois.readObject());
            }
            return drivingRoutes;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private List<JSONObject> getBaiduApiResult(NetworkNode origins, List<NetworkNode> destinations) {
        List<JSONObject> result = new ArrayList<JSONObject>();
        StringBuilder originsParam = new StringBuilder();
        StringBuilder destinationsParam = new StringBuilder();
        originsParam.append(origins.getCoordinateX()).append(",").append(origins.getCoordinateY());

        for (NetworkNode node : destinations) {
            destinationsParam.append(node.getCoordinateX()).append(",").append(node.getCoordinateY()).append("|");
        }
        destinationsParam.deleteCharAt(destinationsParam.lastIndexOf("|"));
        String url = String.format("http://api.map.baidu.com/routematrix/v2/driving?output=json&origins=%s&destinations=%s&ak=%s", URLEncoder.encode(originsParam.toString()), URLEncoder.encode(destinationsParam.toString()), "NURx5GUAQ1IBZVBMCQSpYppRsDdTpbxG");

        CloseableHttpClient client = HttpClients.createDefault();
        try {
            HttpGet httpGet = new HttpGet(url);
            HttpResponse httpResponse = client.execute(httpGet);
            if (httpResponse.getStatusLine().getStatusCode() == 200) {
                HttpEntity httpEntity = httpResponse.getEntity();
                String text = EntityUtils.toString(httpEntity);//取出应答字符串
                JSONObject json = JSONObject.parseObject(text);
                JSONArray array = json.getJSONArray("result");
                for (int i = 0; i < array.size(); i++) {
                    result.add(array.getJSONObject(i));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    @Permission("1001")
    @RequestMapping("/list")
    public String list(Model model) {
        EntityWrapper<Project> wrapper = new EntityWrapper<Project>();
        wrapper.eq("operator_id",getCurrentUserId());
        wrapper.in("state", Arrays.asList("1", "2"));
        model.addAttribute("prjList", projectService.selectList(wrapper));
        return pjaxPath("/file/network_list", model);
    }

    @ResponseBody
    @Permission("1001")
    @RequestMapping("/getData")
    public String getData(Page<NetworkNode> page, String batchId) {
        page = new Page<NetworkNode>(page.getCurrent(), page.getSize());
        EntityWrapper<NetworkNode> wrapper = new EntityWrapper<NetworkNode>();
        wrapper.eq("operator_id", getCurrentUserId());
        if(StringUtils.isNotEmpty(batchId)){
            wrapper.eq("batch_Id", batchId);
        }
        wrapper.orderBy("create_time", false);
        wrapper.orderBy("node_type");
        page = networkNodeService.selectPage(page, wrapper);
        List<NetworkNode> networkNodeList = page.getRecords();
        if (networkNodeList.size() > 0) {
            Project project = projectService.selectById(networkNodeList.get(0).getBatchId());
            for (NetworkNode node : networkNodeList) {
                node.setBatchName(project == null ? "--" : project.getName());
                node.setNodeTypeDesc(NodeTypeEnum.valueOf(node.getNodeType()).getDesc());
            }
        }
        return jsonPage(page);
    }

    @ResponseBody
    @Permission("1001")
    @RequestMapping("/city/groupTable")
    public String groupTable() throws Exception {
        ParamMap<String, Object> pm = getParameterMap();
        List<LinkedHashMap<String, Object>> ret=getCityAll(pm);
        return callbackSuccess(ret);
    }
    public List<LinkedHashMap<String, Object>> getCityAll(ParamMap<String, Object> pm){
        JSONObject rets=new JSONObject();
        //数据源
        HashMap<String, CityOrder> hm1 = getMap();
        List<Map.Entry<String,CityOrder>> citylist = new ArrayList<Map.Entry<String,CityOrder>>(hm1.entrySet());
        LinkedHashMap<String,CityDrivingRoute> cityDrivingRoute;
        //排序
        List<Map.Entry<String,CityOrder>> list = getlist(citylist);
        List<LinkedHashMap<String, Object>> ret1;
        double Rack=0;
        double RackNumber=0;
        String name=null;
        int m=Integer.valueOf(pm.get("isNumber").toString());//多少个数据不处理
        for (int i=0;i<m;i++){
            name=list.get(list.size()-i-1).getValue().getName();
            hm1.remove(name);
        }
        CityPeopleGroup cityPeopleGroup=new CityPeopleGroup();
        //第一次组合
        cityDrivingRoute = cityPeopleGroup.orderHashMap(hm1,pm);
        //加上剩余的组合
        for (int i=0;i<m;i++){
            CityDrivingRoute cityDrivingRoute1=new CityDrivingRoute(list.get(list.size()-i-1).getValue(),0,null,0,null);
            cityDrivingRoute.put(list.get(list.size()-i-1).getValue().getName(),cityDrivingRoute1);
        }
        ret1=cityPeopleGroup.orderCombination(cityDrivingRoute,pm);
        return ret1;
    }
    public HashMap<String, CityOrder> getMap(){
        EntityWrapper<CityOrder> wrapper = new EntityWrapper<CityOrder>();
        wrapper.eq("batch_id", getProjectId());
        final List<CityOrder> nodeList = cityOrderService.selectList(wrapper);
        HashMap<String, CityOrder> hm1=new HashMap<String, CityOrder>();
        for(int i=0;i<nodeList.size();i++){
            hm1.put(nodeList.get(i).getName(), nodeList.get(i));
        }
        return hm1;
    }
    public List<Map.Entry<String,CityOrder>> getlist(List<Map.Entry<String,CityOrder>> list){
        Collections.sort(list, new Comparator<Map.Entry<String,CityOrder>>() {
            @Override
            public int compare(Map.Entry<String,CityOrder> o1,Map.Entry<String,CityOrder> o2) {
                return o1.getValue().getOrderPositive().compareTo(o2.getValue().getOrderPositive());
            }
        });
        return list;
    }

    @ResponseBody
    @Permission("1001")
    @RequestMapping("/city/transportTable")
    public String transportTable() throws Exception {
        EntityWrapper<NetworkNode> wrapper = new EntityWrapper<NetworkNode>();
        wrapper.eq("batch_id", getMaxId());
        wrapper.eq("node_type", "2");
        NetworkNode factory = networkNodeService.selectOne(wrapper);
        List<Map<String, Object>> ret = new ArrayList<Map<String, Object>>();
        List<DrivingRoute> drivingRoutes = readObj(getMaxId());
        LinkedHashMap<NetworkNode, List<NetworkNode>> maps = Test.getMaps(drivingRoutes);
        Map<String, Object> map = null;
        for (Map.Entry<NetworkNode, List<NetworkNode>> entry : maps.entrySet()) {
            map = new LinkedHashMap<String, Object>();
            Long distance = getDistance1(drivingRoutes, factory, entry.getKey());
            Long duration = getDuration(drivingRoutes, factory, entry.getKey());
            String nodeName1 = entry.getKey().getNodeName();
            String nodeName2 = "";
            String nodeName3 = "";
            List<NetworkNode> children = entry.getValue();
            if (children != null) {
                if (children.size() > 0) {
                    distance += getDistance1(drivingRoutes, entry.getKey(), children.get(0));
                    duration += getDuration(drivingRoutes, entry.getKey(), children.get(0));
                    nodeName2 = children.get(0).getNodeName();
                }
                if (children.size() == 2) {
                    if (children.size() > 1) {
                        distance += getDistance1(drivingRoutes, children.get(0), children.get(1));
                        duration += getDuration(drivingRoutes, children.get(0), children.get(1));
                        nodeName3 = children.get(1).getNodeName();
                    }
                }
            }
            map.put("nodeName1", nodeName1);
            map.put("nodeName2", nodeName2);
            map.put("nodeName3", nodeName3);
            map.put("distance", distance);
            map.put("duration", duration);
            ret.add(map);
        }
        return callbackSuccess(ret);
    }

    private Long getDistance1(List<DrivingRoute> drivingRoutes, NetworkNode node1, NetworkNode node2) {
        for (DrivingRoute route : drivingRoutes) {
            if (route.isPath(node1, node2)) {
                return route.distance;
            }
        }
        return Double.valueOf(Math.random() * 10000).longValue();
    }

    private Long getDuration(List<DrivingRoute> drivingRoutes, NetworkNode node1, NetworkNode node2) {
        for (DrivingRoute route : drivingRoutes) {
            if (route.isPath(node1, node2)) {
                return route.duration;
            }
        }
        return Double.valueOf(Math.random() * 800).longValue();
    }

    @ResponseBody
    @Permission("1001")
    @RequestMapping("/city/force")
    public String force() throws Exception {
        JSONObject ret = new JSONObject();
        JSONArray nodes = new JSONArray();
        JSONArray links = new JSONArray();
        ParamMap<String, Object> pm = getParameterMap();
        //数据源
        HashMap<String, CityOrder> hm1 = getMap();
        HashMap<String, CityOrder> hm2=new HashMap<String, CityOrder>();
        hm2.putAll(hm1);
        List<Map.Entry<String,CityOrder>> citylist = new ArrayList<Map.Entry<String,CityOrder>>(hm1.entrySet());
        //排序
        List<Map.Entry<String,CityOrder>> list = getlist(citylist);
        String name=null;
        //定义起始点
        String startNode=null;
        int m=2;//多少个数据不处理
        for (int i=0;i<m;i++){
            startNode=list.get(list.size()-i-1).getValue().getDistributionCenter();
            name=list.get(list.size()-i-1).getValue().getName();
            hm1.remove(name);
        }
        List<LinkedHashMap<String, Object>> rets;
        CityPeopleGroup cityPeopleGroup=new CityPeopleGroup();
        LinkedHashMap<String,CityDrivingRoute> cityDrivingRoute;
        //第一次组合
        cityDrivingRoute = cityPeopleGroup.orderHashMap(hm1,pm);
        //加上剩余的组合
        for (int i=0;i<m;i++){
            CityDrivingRoute cityDrivingRoute1=new CityDrivingRoute(list.get(list.size()-i-1).getValue(),0,null,0,null);
            cityDrivingRoute.put(list.get(list.size()-i-1).getValue().getName(),cityDrivingRoute1);
        }
        rets=cityPeopleGroup.orderCombination(cityDrivingRoute,pm);

        for (int i=0;i<m;i++){
            name=list.get(list.size()-i-1).getValue().getName();
            JSONObject link1 = new JSONObject();
            link1.put("source", name);
            link1.put("target", startNode);
            links.add(link1);
        }
        //用来解决nodes的数据来源
        List<String> nodeLists = new ArrayList<String>();
        //links数据添加
        for (int i=0;i<rets.size();i++){
            JSONObject link = new JSONObject();
            link.put("source", rets.get(i).get("nodeName1"));
            link.put("target",startNode);
            links.add(link);
            if(rets.get(i).get("nodeName2").toString()!=null && rets.get(i).get("nodeName2").toString().length()!=0){
                link = new JSONObject();
                link.put("source", rets.get(i).get("nodeName2"));
                link.put("target", rets.get(i).get("nodeName1"));
                links.add(link);
            }
            if(rets.get(i).get("nodeName3").toString()!=null && rets.get(i).get("nodeName3").toString().length()!=0){
                link = new JSONObject();
                link.put("source", rets.get(i).get("nodeName3"));
                link.put("target", rets.get(i).get("nodeName2"));
                links.add(link);
            }
        }
        for (String node : hm2.keySet()) {
            JSONObject nodeJson = new JSONObject();
            nodeJson.put("category", NodeTypeEnum.DISTRIBUTE_CENTER.type == hm2.get(node).getType() ? 0 : 1);
            nodeJson.put("name", hm2.get(node).getName());
            nodeJson.put("value", NodeTypeEnum.DISTRIBUTE_CENTER.type == hm2.get(node).getType() ? 100 : Math.ceil(hm2.get(node).getOrderPositive().doubleValue() / 30 / 550 *1.3));
            nodes.add(nodeJson);
        }
        JSONObject nodeJson = new JSONObject();
        nodeJson.put("category", 0);
        nodeJson.put("name", startNode);
        nodeJson.put("value", "");
        nodes.add(nodeJson);
        ret.put("nodes", nodes);
        ret.put("links", links);
        return callbackSuccess(ret);
    }

    @ResponseBody
    @Permission("1001")
    @RequestMapping("/city/bar")
    public String cityBar() throws Exception {
        //获取到数据
        ParamMap<String, Object> pm = getParameterMap();
        pm.put("isNumber",2);
        pm.put("days",30);
        pm.put("parameter",550);
        pm.put("coefficient",1.3);
        pm.put("distance1",5);
        pm.put("distance2",10);
        pm.put("lnglat",1);
        //数据源
        HashMap<String, CityOrder> hm1 = getMap();
        List<Map.Entry<String,CityOrder>> citylist = new ArrayList<Map.Entry<String,CityOrder>>(hm1.entrySet());
        //排序
        List<Map.Entry<String,CityOrder>> list = getlist(citylist);
        String name=null;
        int m=2;//多少个数据不处理
        for (int i=0;i<m;i++){
            name=list.get(list.size()-i-1).getValue().getName();
            hm1.remove(name);
        }
        CityPeopleGroup cityPeopleGroup=new CityPeopleGroup();
        List<LinkedHashMap<String, Object>> rets;
        LinkedHashMap<String,CityDrivingRoute> cityDrivingRoute;
        //第一次组合
        cityDrivingRoute = cityPeopleGroup.orderHashMap(hm1,pm);
        //加上剩余的组合
        for (int i=0;i<m;i++){
            CityDrivingRoute cityDrivingRoute1=new CityDrivingRoute(list.get(list.size()-i-1).getValue(),0,null,0,null);
            cityDrivingRoute.put(list.get(list.size()-i-1).getValue().getName(),cityDrivingRoute1);
        }
        rets=cityPeopleGroup.orderCombination(cityDrivingRoute,pm);
        JSONObject ret = new JSONObject();
        Map<String, Object> map = null;
        JSONArray t = new JSONArray();//分组
        JSONArray a1 = new JSONArray();//人均作业能力
        JSONArray a2 = new JSONArray();//人均回收作业能力
        JSONArray a3 = new JSONArray();
        int count = 1;
        for(int i=0;i<rets.size();i++){
            double manWorkTotal=Double.parseDouble(rets.get(i).get("shelf").toString());
            double manWorkNumber=Double.parseDouble(rets.get(i).get("distribute").toString());
            double recovery2=Double.parseDouble(rets.get(i).get("recovery").toString());
            double manWorkTime=Math.ceil(manWorkTotal/manWorkNumber);
            double manWorkrecovery=Math.ceil(manWorkTotal/recovery2);
            a1.add(manWorkTime);
            a2.add(manWorkrecovery);
            t.add(count++ + "组");
        }
        ret.put("x", t);
        ret.put("s1", a1);
        ret.put("s2", a2);
        ret.put("s3", a3);
        return callbackSuccess(ret);
    }

    @ResponseBody
    @Permission("1001")
    @RequestMapping("/city/bar1")
    public String cityBar1() throws Exception {
        EntityWrapper<NetworkNode> wrapper = new EntityWrapper<NetworkNode>();
        wrapper.eq("batch_id", getMaxId());
        wrapper.eq("node_type", "2");
        NetworkNode factory = networkNodeService.selectOne(wrapper);
        List<DrivingRoute> drivingRoutes = readObj(getMaxId());
        LinkedHashMap<NetworkNode, List<NetworkNode>> maps = Test.getMaps(drivingRoutes);
        JSONObject ret = new JSONObject();
        Map<String, Object> map = null;
        JSONArray t = new JSONArray();
        JSONArray a1 = new JSONArray();
        JSONArray a2 = new JSONArray();
        JSONArray a3 = new JSONArray();
        int count = 1;
        for (Map.Entry<NetworkNode, List<NetworkNode>> entry : maps.entrySet()) {
            map = new LinkedHashMap<String, Object>();
            Long distance = getDistance1(drivingRoutes, factory, entry.getKey());
            Long duration = getDuration(drivingRoutes, factory, entry.getKey());
            List<NetworkNode> children = entry.getValue();
            if (children != null) {
                if (children.size() > 0) {
                    distance += getDistance1(drivingRoutes, entry.getKey(), children.get(0));
                    duration += getDuration(drivingRoutes, entry.getKey(), children.get(0));
                }
                if (children.size() == 2) {
                    if (children.size() > 1) {
                        distance += getDistance1(drivingRoutes, children.get(0), children.get(1));
                        duration += getDuration(drivingRoutes, children.get(0), children.get(1));
                    }
                }
            }
            a1.add(distance);
            a2.add(duration);
            a3.add(Math.round(distance * 1.45));
            t.add(count++ + "组");
        }
        ret.put("x", t);
        ret.put("s1", a1);
        ret.put("s2", a2);
        ret.put("s3", a3);
        return callbackSuccess(ret);
    }
    @ResponseBody
    @Permission("1001")
    @RequestMapping("/city/barManGroup")
    public String cityBarManGroup() throws Exception {
        //获取到数据
        ParamMap<String, Object> pm = getParameterMap();
        //数据源
        HashMap<String, CityOrder> hm1 = getMap();
        List<Map.Entry<String,CityOrder>> citylist = new ArrayList<Map.Entry<String,CityOrder>>(hm1.entrySet());
        //排序
        List<Map.Entry<String,CityOrder>> list = getlist(citylist);
        String name=null;
        int m=2;//多少个数据不处理
        for (int i=0;i<m;i++){
            name=list.get(list.size()-i-1).getValue().getName();
            hm1.remove(name);
        }
        CityPeopleGroup cityPeopleGroup=new CityPeopleGroup();
        List<LinkedHashMap<String, Object>> rets;
        LinkedHashMap<String,CityDrivingRoute> cityDrivingRoute;
        //第一次组合
        cityDrivingRoute = cityPeopleGroup.orderHashMap(hm1,pm);
        //加上剩余的组合
        for (int i=0;i<m;i++){
            CityDrivingRoute cityDrivingRoute1=new CityDrivingRoute(list.get(list.size()-i-1).getValue(),0,null,0,null);
            cityDrivingRoute.put(list.get(list.size()-i-1).getValue().getName(),cityDrivingRoute1);
        }
        rets=cityPeopleGroup.orderCombination(cityDrivingRoute,pm);
        JSONObject ret = new JSONObject();
        Map<String, Object> map = null;
        JSONArray t = new JSONArray();
        JSONArray a1 = new JSONArray();
        JSONArray a2 = new JSONArray();
        JSONArray a3 = new JSONArray();
        int count = 1;
        for(int i=0;i<rets.size();i++){
            double q1=Double.valueOf(rets.get(i).get("nodeName1Number").toString());
            double q2=Double.valueOf(rets.get(i).get("nodeName2Number").toString());
            double q3=Double.valueOf(rets.get(i).get("nodeName3Number").toString());
            q1=q1+q2+q3;
            a1.add(Math.ceil(q1/550/30*1.3));
            a2.add(rets.get(i).get("distribute"));
            a3.add(rets.get(i).get("recovery"));
            t.add(count++ + "组");
        }
        ret.put("x", t);
        ret.put("s1", a1);
        ret.put("s2", a2);
        ret.put("s3", a3);
        return callbackSuccess(ret);
    }

    /**
     * 配送人员忙闲
     * @return
     * @throws Exception
     */
    @ResponseBody
    @Permission("1001")
    @RequestMapping("/city/bar3")
    public String cityBar3() throws Exception {
        //获取到数据
        String object1=request.getParameter("params1");
        String object2=request.getParameter("params2");
        String object3=request.getParameter("params3");
        String object4=request.getParameter("params4");
        //对获取到的数据进行处理
        double objectWorkTime=Double.valueOf(object1);
        double UniteliveryTime=60/Double.valueOf(object2);
        double workerdaytime=objectWorkTime*UniteliveryTime;
        double recovery=60/Double.valueOf(object3);
        double timeRecovery=objectWorkTime*recovery;
        //数据源
        HashMap<String, CityOrder> hm1 = getMap();
        List<Map.Entry<String,CityOrder>> citylist = new ArrayList<Map.Entry<String,CityOrder>>(hm1.entrySet());
        //排序
        List<Map.Entry<String,CityOrder>> list = getlist(citylist);
        String name=null;
        int m=2;//多少个数据不处理
        for (int i=0;i<m;i++){
            name=list.get(list.size()-i-1).getValue().getName();
            hm1.remove(name);
        }
        //数据展示处理
        CityPeopleGroup cityPeopleGroup=new CityPeopleGroup();
        List<LinkedHashMap<String, Object>> rets=cityPeopleGroup.MaxHashMap(hm1,"YMax",workerdaytime,timeRecovery);

        JSONObject ret = new JSONObject();
        JSONArray t = new JSONArray();//分组
        JSONArray a1 = new JSONArray();//人均配送工作时间
        JSONArray a2 = new JSONArray();//人均配送空闲时间
        JSONArray a3 = new JSONArray();//人均回收工作时间
        JSONArray a4 = new JSONArray();//人均回收空闲时间
        int count = 1;
        for(int i=0;i<rets.size();i++){
            double shelf=Double.valueOf(rets.get(i).get("shelf").toString());//总的工作量
            double distribute=Double.valueOf(rets.get(i).get("distribute").toString());//配送人员工作时间
            double recoveryCount=Double.valueOf(rets.get(i).get("recovery").toString());//回收人员工作时间
            double timeWorkDistribution=Math.ceil(shelf/distribute/60*Double.valueOf(object2));
            double timeWorkRecovery=Math.ceil(shelf/recoveryCount/60*Double.valueOf(object3));
            a1.add(timeWorkDistribution);
            a2.add(Double.valueOf(object1)-timeWorkDistribution);
            a3.add(timeWorkRecovery*(-1));
            a4.add(Double.valueOf(object1)-timeWorkRecovery);
            t.add(count++ + "组");
        }
        //六院和瑞金特殊处理
        for (int i=0;i<m;i++){
            double Rack=list.get(list.size()-1-i).getValue().getOrderPositive().doubleValue();
            double RackNumber=Math.ceil(Rack/550/30*1.3/workerdaytime);
            double Rackrecovery=Math.ceil(Rack/550/30*1.3/timeRecovery);//回收人数
            double manWorkTime2=Math.ceil(Rack/550/30*1.3/RackNumber/60*Double.valueOf(object2));
            double manWorktime3=Math.ceil(Rack/550/30*1.3/Rackrecovery/60*Double.valueOf(object2));
            a1.add(manWorkTime2);
            a2.add(Double.valueOf(object1)-manWorkTime2);
            a3.add(manWorktime3*(-1));
            a4.add(Double.valueOf(object1)-manWorktime3);
            t.add(count++ + "组");
        }

        ret.put("x", t);
        ret.put("s1", a1);
        ret.put("s2", a2);
        ret.put("s3", a3);
        ret.put("s4", a4);
        return callbackSuccess(ret);
    }
    /**
     * 配送人员忙闲比
     * @return
     * @throws Exception
     */
    @ResponseBody
    @Permission("1001")
    @RequestMapping("/city/bar4")
    public String cityBar4() throws Exception {
        DecimalFormat df=new DecimalFormat(".##");//保留2位小数
        //获取到数据
        ParamMap<String, Object> pm = getParameterMap();
        pm.put("isNumber",2);
        pm.put("days",30);
        pm.put("parameter",550);
        pm.put("coefficient",1.3);
        pm.put("distance1",5);
        pm.put("distance2",10);
        pm.put("lnglat",1);
        //数据源
        HashMap<String, CityOrder> hm1 = getMap();
        List<Map.Entry<String,CityOrder>> citylist = new ArrayList<Map.Entry<String,CityOrder>>(hm1.entrySet());
        //排序
        List<Map.Entry<String,CityOrder>> list = getlist(citylist);
        String name=null;
        int m=2;//多少个数据不处理
        for (int i=0;i<m;i++){
            name=list.get(list.size()-i-1).getValue().getName();
            hm1.remove(name);
        }
        CityPeopleGroup cityPeopleGroup=new CityPeopleGroup();
        List<LinkedHashMap<String, Object>> rets;
        LinkedHashMap<String,CityDrivingRoute> cityDrivingRoute;
        //第一次组合
        cityDrivingRoute = cityPeopleGroup.orderHashMap(hm1,pm);
        //加上剩余的组合
        for (int i=0;i<m;i++){
            CityDrivingRoute cityDrivingRoute1=new CityDrivingRoute(list.get(list.size()-i-1).getValue(),0,null,0,null);
            cityDrivingRoute.put(list.get(list.size()-i-1).getValue().getName(),cityDrivingRoute1);
        }
        rets=cityPeopleGroup.orderCombination(cityDrivingRoute,pm);
        JSONObject ret = new JSONObject();
        Map<String, Object> map = null;
        JSONArray t = new JSONArray();//分组
        JSONArray a1 = new JSONArray();//人均配送百分比
        JSONArray a2 = new JSONArray();//人均配送空闲时间
        JSONArray a3 = new JSONArray();//人均回收工作时间
        JSONArray a4 = new JSONArray();//人均回收空闲时间
        int count = 1;
        for(int i=0;i<rets.size();i++){
            double shelf=Double.valueOf(rets.get(i).get("shelf").toString());//总的工作量
            double distribute=Double.valueOf(rets.get(i).get("distribute").toString());//配送人员工作
            double recoveryCount=Double.valueOf(rets.get(i).get("recovery").toString());//回收人员工作
            double timeWorkDistribution=shelf/distribute/60*Double.valueOf(pm.get("cost1").toString());
            double timeWorkRecovery=Math.ceil(shelf/recoveryCount/60*Double.valueOf(pm.get("cost2").toString()));
            a1.add(df.format(timeWorkDistribution/Double.valueOf(pm.get("dayTime").toString())*100));
            a2.add(Double.valueOf(pm.get("dayTime").toString())-timeWorkDistribution);
            a3.add(timeWorkRecovery);
            a4.add(Double.valueOf(pm.get("dayTime").toString())-timeWorkRecovery);
            t.add(count++ + "组");
        }
        ret.put("x", t);
        ret.put("s1", a1);
        return callbackSuccess(ret);
    }

    /**
     * 配送人员忙闲比
     * @return
     * @throws Exception
     */
    @ResponseBody
    @Permission("1001")
    @RequestMapping("/city/bar41")
    public String cityBar41() throws Exception {
        DecimalFormat df=new DecimalFormat(".##");//保留2位小数
        //获取到数据
        ParamMap<String, Object> pm = getParameterMap();
        pm.put("isNumber",2);
        pm.put("days",30);
        pm.put("parameter",550);
        pm.put("coefficient",1.3);
        pm.put("distance1",5);
        pm.put("distance2",10);
        pm.put("lnglat",1);
        //数据源
        HashMap<String, CityOrder> hm1 = getMap();
        List<Map.Entry<String,CityOrder>> citylist = new ArrayList<Map.Entry<String,CityOrder>>(hm1.entrySet());
        //排序
        List<Map.Entry<String,CityOrder>> list = getlist(citylist);
        String name=null;
        int m=2;//多少个数据不处理
        for (int i=0;i<m;i++){
            name=list.get(list.size()-i-1).getValue().getName();
            hm1.remove(name);
        }
        CityPeopleGroup cityPeopleGroup=new CityPeopleGroup();
        List<LinkedHashMap<String, Object>> rets;
        LinkedHashMap<String,CityDrivingRoute> cityDrivingRoute;
        //第一次组合
        cityDrivingRoute = cityPeopleGroup.orderHashMap(hm1,pm);
        //加上剩余的组合
        for (int i=0;i<m;i++){
            CityDrivingRoute cityDrivingRoute1=new CityDrivingRoute(list.get(list.size()-i-1).getValue(),0,null,0,null);
            cityDrivingRoute.put(list.get(list.size()-i-1).getValue().getName(),cityDrivingRoute1);
        }
        rets=cityPeopleGroup.orderCombination(cityDrivingRoute,pm);
        JSONObject ret = new JSONObject();
        JSONArray t = new JSONArray();//分组
        JSONArray a1 = new JSONArray();//人均配送百分比
        JSONArray a2 = new JSONArray();//人均配送空闲时间
        JSONArray a3 = new JSONArray();//人均回收工作时间
        JSONArray a4 = new JSONArray();//人均回收空闲时间
        int count = 1;
        for(int i=0;i<rets.size();i++){
            double shelf=Double.valueOf(rets.get(i).get("shelf").toString());//总的工作量
            double distribute=Double.valueOf(rets.get(i).get("distribute").toString());//配送人员工作时间
            double recoveryCount=Double.valueOf(rets.get(i).get("recovery").toString());//回收人员工作时间
            double timeWorkDistribution=Math.ceil(shelf/distribute/60*Double.valueOf(pm.get("cost1").toString()));
            double timeWorkRecovery=shelf/recoveryCount/60*Double.valueOf(pm.get("cost2").toString());
            a1.add(df.format(timeWorkRecovery/Double.valueOf(pm.get("dayTime").toString())*100));
            a2.add(Double.valueOf(pm.get("dayTime").toString())-timeWorkDistribution);
            a3.add(timeWorkRecovery);
            a4.add(Double.valueOf(pm.get("dayTime").toString())-timeWorkRecovery);
            t.add(count++ + "组");
        }
        ret.put("x", t);
        ret.put("s1", a1);
        return callbackSuccess(ret);
    }
    private Long getMaxId() {
        EntityWrapper<NetworkNode> wrapper = new EntityWrapper<NetworkNode>();
        wrapper.eq("operator_id", getCurrentUserId());
        wrapper.orderBy("create_time", false);
        NetworkNode node = networkNodeService.selectOne(wrapper);
        return node.getBatchId();
    }







}
